﻿using System;
using System.Collections.Generic;
using System.Text;
using Common.Utils;

using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using System.Configuration;

namespace Common.Service
{
    public partial class ServiceContainer
    {
        private static readonly IWindsorContainer container;

        /// <summary>
        /// 构造静态 IWindsorContainer 实例。
        /// </summary>
        static ServiceContainer()
        {
            object section = ConfigurationManager.GetSection("castle");
            if (section != null)
            {
                container = new StartsWithAppConfigContainer();
            }
        }

        /// <summary>
        /// 返回服务容器。
        /// </summary>
        public static IWindsorContainer Container
        {
            get { return container; }
        }

        /// <summary>
        /// 获取服务对象。
        /// </summary>
        /// <param name="serviceType"></param>
        /// <returns></returns>
        public static object GetService(Type type)
        {
            if (type == null)
            {
                throw new NullReferenceException();
            }
            object obj = null;
            obj = container.GetService(type);
            
            if (obj == null)
            {
                throw new Exception(string.Format("在配置文件中没有找到接口{0}的实现", type.ToString()));
            }
            return obj;
        }

        /// <summary>
        /// 获取服务对象。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetService<T>() where T : class
        {
            T t = GetServiceById<T>("");
            if (t == null)
            {
                throw new Exception(string.Format("在配置文件中没有找到接口{0}的实现", typeof(T).ToString()));
            }
            return t;
        }

        public static T GetService<T>(string id) where T : class
        {
            T t = GetServiceById<T>(id);
            if (t == null)
            {
                throw new Exception(string.Format("在配置文件中没有找到id为{1}接口{0}的实现", typeof(T).ToString(), id));
            }
            return t;
        }

        public static T GetService<T>(T defaultType) where T : class
        {
            T t = GetServiceById<T>("");
            if (t == null)
            {
                t = defaultType;
            }
            return t;
        }

        static T GetServiceById<T>(string id) where T : class
        {
            Type type = typeof(T);
            T t = default(T);

            if (type.IsInterface) //IoC
            {
                if (container == null)
                {
                    return null;
                }
                if (string.IsNullOrEmpty(id))
                {
                    t = container.GetService<T>();
                }
                else
                {
                    t = container.Resolve<T>(id);
                }
            }
            else if (type.IsClass) //Create new instance
            {
                t = (T)Activator.CreateInstance(type);
            }
            else
            {
                if (container == null)
                {
                    return null;
                }
                t = (T)container.GetService(type);
            }
            return t;
        }

        public static T[] GetAll<T>() where T : class
        {
            return container.ResolveAll<T>();
        }

        /// <summary>
        /// 释放对服务对象的引用。
        /// </summary>
        /// <param name="instance"></param>
        public static void Release(object instance)
        {
            container.Release(instance);
        }
    }

    internal class StartsWithAppConfigContainer : WindsorContainer
    {
        public StartsWithAppConfigContainer()
            : base(new XmlInterpreter())
        {

        }
    }

    internal class StartsWithXmlConfigContainer : WindsorContainer
    {
        public StartsWithXmlConfigContainer(string fileName)
            : base(new XmlInterpreter(fileName))
        {

        }
    }
}
